#include "seat_wrapper.h"
#include "wlroots-full.hpp"
#include "server.h"

SeatWrapper::SeatWrapper(Server *server)
    : m_server(server)
{
    m_seat = wlr_seat_create(m_server->m_display, "seat0");

    m_request_cursor.connect(&m_seat->events.request_set_cursor, [=](void* data) {
        struct wlr_seat_pointer_request_set_cursor_event *event = (struct wlr_seat_pointer_request_set_cursor_event*)data;
        request_cursor(event);
    });

    m_request_set_selection.connect(&m_seat->events.request_set_selection, [=](void* data) {
        struct wlr_seat_request_set_selection_event *event = (struct wlr_seat_request_set_selection_event *)data;
        request_set_selection(event);
    });
}

SeatWrapper::~SeatWrapper()
{

}

void SeatWrapper::focus_surface(wlr_surface *surface)
{
#if 0
    /* Respect layer-shell exclusive keyboard-interactivity. */
    if (seat->focused_layer && seat->focused_layer->current.keyboard_interactive
                                   == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) {
        return;
    }
#endif
    focus(surface, /*is_lock_surface*/ false);
}

void SeatWrapper::request_cursor(wlr_seat_pointer_request_set_cursor_event *event)
{
    struct wlr_seat_client *focused_client = m_seat->pointer_state.focused_client;
    /* This can be sent by any client, so we check to make sure this one is
     * actually has pointer focus first. */
    if (focused_client == event->seat_client) {
        /* Once we've vetted the client, we can tell the cursor to use the
         * provided surface as the cursor image. It will set the hardware cursor
         * on the output that it's currently on and continue to do so as the
         * cursor moves between outputs. */
        // wlr_cursor_set_surface(server->cursor, event->surface,
                               // event->hotspot_x, event->hotspot_y);
        sig_request_cursor.emit(event->surface, event->hotspot_x, event->hotspot_y);
    }
}

void SeatWrapper::request_set_selection(wlr_seat_request_set_selection_event *event)
{
    wlr_seat_set_selection(m_seat, event->source, event->serial);
}

void SeatWrapper::focus(wlr_surface *surface, bool is_lock_surface)
{
    /*
     * Respect session lock. This check is critical, DO NOT REMOVE.
     * It should also come before the !surface condition, or the
     * lock screen may lose focus and become impossible to unlock.
     */
#if 0
    if (m_server->session_lock && !is_lock_surface) {
        return;
    }
#endif

    if (!surface) {
        wlr_seat_keyboard_notify_clear_focus(m_seat);
        return;
    }

#if 0
    /* Respect input inhibit (also used by some lock screens) */
    if (input_inhibit_blocks_surface(seat, surface->resource)) {
        return;
    }

    /*
     * Key events associated with keybindings (both pressed and released)
     * are not sent to clients. When changing surface-focus it is therefore
     * important not to send the keycodes of _all_ pressed keys, but only
     * those that were actually _sent_ to clients (that is, those that were
     * not bound).
     */
#endif

#if 0
    uint32_t *pressed_sent_keycodes = key_state_pressed_sent_keycodes();
    int nr_pressed_sent_keycodes = key_state_nr_pressed_sent_keycodes();

    struct wlr_keyboard *kb = &seat->keyboard_group->keyboard;
    wlr_seat_keyboard_notify_enter(seat->seat, surface,
                                   pressed_sent_keycodes, nr_pressed_sent_keycodes, &kb->modifiers);
#else
    struct wlr_keyboard* kb = wlr_seat_get_keyboard(m_seat);
    if (kb) {
        wlr_seat_keyboard_notify_enter(m_seat, surface,
                                       kb->keycodes, kb->num_keycodes, &kb->modifiers);
    } else {
        wlr_seat_keyboard_notify_enter(m_seat, surface, NULL, 0, NULL);
    }
#endif

#if 0
    struct wlr_pointer_constraint_v1 *constraint =
        wlr_pointer_constraints_v1_constraint_for_surface(server->constraints,
                                                          surface, seat->seat);
    constrain_cursor(server, constraint);
#endif
}
